#include <windows.h>
#include <iostream>
#include <string>

#include "Systems\Logger.h"
#include "Systems\BasicWindow.h"
#include "Graphics\DXManager.h"
#include "Systems\GameManager.h"
#include "Systems\InputManager.h"
#include "Systems\ResourceManager.h"

using namespace std;

//#define CheckFatalDxError(hr) CheckHRESULT(__FILE__,__LINE__,hr, Logger::FATAL)
//#define CheckRecoverableDxError(hr) CheckHRESULT(__FILE__,__LINE__,hr, Logger::RECOVERABLE)

DXManager* gpDX = new DXManager;
BasicWindow* gpBW = new BasicWindow;
InputManager* gpIM = new InputManager;
GameManager* gpGM = new GameManager;
ResourceManager* gpRM = new ResourceManager;
Logger gLogger;

/*
void CheckHRESULT(const char *file, int line, HRESULT hr, Logger::Level logLevel)
{
	if (FAILED(hr))
	{
		char desc[1024];
		//sprintf(desc,"(DX) %s - %s",DXGetErrorString(hr),DXGetErrorDescription(hr));

		// Output the file and line number in the correct format + the above DX error
		char buf[2048];
		sprintf(buf,"%s(%d) : Error: %s\n", file, line, desc);
		Logger::getInstance().logError(logLevel, buf);
		if (logLevel == Logger::FATAL)
		{
			exit(-2);
		}

	}
}*/

bool initSystems(HINSTANCE hInstance, int nCmdShow)
{
	///Initialize logger
	Logger::getInstance().init();

	//seed random number generator
	srand(timeGetTime());

	//create input manager
	gpIM->Create();

	//create resource manager
	gpRM->Create();

	//create window
	HWND hwnd = gpBW->Create(hInstance, nCmdShow);
	if (hwnd != NULL)
	{
		//create DirectX wrapper
		if (gpDX->Create(hwnd))
		{
			//finally, create game manager
			gpGM->Create();
			return true;
		}
	}

	return false;
}

//WinMain - based on theForger's tutorial - http://winprog.org/tutorial/simple_window.html
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	if (initSystems(hInstance, nCmdShow))
	{
		MSG msg;
		ZeroMemory(&msg, sizeof(msg));

		gpBW->Show();

		while (msg.message != WM_QUIT)
		{
			// badly behaved message loop -- do our own work if no message is waiting for us
			if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
			else
			{
				gpGM->Loop();
			}
		}

		return msg.wParam;
	}

	//fall through error case
	return -1;
}
